/* 
文章控制器
场景：创建文章
*/

const HttpException = require('../exception/http.exception.js');
const User = require('../model/user');
const Article = require('../model/article');
const Tag = require('../model/tag');
const { getSlug } = require('../utils/slug');
const sequelize = require('../db/sequelize.js');

function handleArticle(article, author, favoriteCount, favorited) {
    //标签处理
    const tags = []
    for (const tag of article.dataValues.tags) {
        tags.push(tag.name)
    }
    article.dataValues.tags = tags
    //作者信息处理
    delete author.dataValues.password
    delete article.dataValues.userEmail
    article.dataValues.author = author

    //处理喜欢
    article.dataValues.favoritedCount = favoriteCount//喜欢数量
    article.dataValues.favorited = favorited  //是否喜欢

    return article.dataValues
}

function handleArticle2(article, favoriteCount, favorited) {
    //标签处理
    const tags = []
    for (const tag of article.dataValues.tags) {
        tags.push(tag.name)
    }
    article.dataValues.tags = tags
    let author = article.dataValues.user
    //作者信息处理
    delete author.dataValues.password
    delete article.dataValues.userEmail
    article.dataValues.author = author

    //处理喜欢
    article.dataValues.favoriteCount = favoriteCount//喜欢数量
    article.dataValues.favorited = favorited  //是否喜欢


    return article.dataValues
}

const getFavorite = async (article, currentUser) => {
    //喜欢数量
    const favoriteCount = await article.countUsers()  //获取喜欢的人的数量
    const favoriteUsers = await article.getUsers()  //获取喜欢文章的人

    let allFavoriteEmail = []
    for (const user of favoriteUsers) {
        allFavoriteEmail.push(user.email)
    }
    //当前登录用户是否喜欢
    let favorited = false  //默认 没登录 都显示未喜欢
    if (currentUser) {  //登录了则判断 是否喜欢
        let loginEmail = currentUser.email
        favorited = allFavoriteEmail.includes(loginEmail)
    }
    return { favoriteCount, favorited }
}
//创建标签
const createArticleController = async (req, res, next) => {
    try {
        //00 需要登录 验证token
        //01 获取body 数据，可能含有tags
        const { title, description, body, tags } = req.body.article
        // console.log(title);
        //02 数据验证
        //TODO(自己完成)
        //03验证:登录用户且在数据存在才能创建文章=>作者信息email
        const { email } = req.user
        //3.1) 1.安全验证  2.获取作者信息 给文章返回做准别
        const author = await User.findByPk(email)
        if (!author) {
            throw new HttpException(401, '作者账号不存在', "author user not found")
        }
        // console.log("author99",author);
        //2数据校验
        //04 生成别名
        const slug = getSlug()
        // console.log(slug);

        //05 存储文章
        let article = await Article.create({
            slug,
            title,
            description,
            body,
            userEmail: email

        })
        // console.log(article);
        //06 存储标签：文章和标签关系存储 / 新的标签存储
        for (const t of tags) {
            let existTag = await Tag.findByPk(t)
            if (!existTag) {
                const newTag = await Tag.create({ name: t })
                // console.log(article.__proto__);  
                //article.__proto__原型上的方法 -> addTag
                await article.addTag(newTag)
            } else {//老标签
                //存储老标签和文章的关系
                // console.log(article.__proto__);
                await article.addTag(existTag)
            }
        }
        //07 返回文章:
        //7.1) 获取文章关联标签和作者
        // 编辑（文章）->保存->预览（文章 标签 作者）
        //重新查询确认文章存储成功;获取真正数据库文章关联作者和标签
        article = await Article.findByPk(slug, { include: Tag })
        // console.log(article);
        //7.2) 文章信息进行处理
        article = handleArticle(article, author)
        //7.3) 响应数据

        return res.status(200)
            .json({
                status: 1,
                message: "OK",
                data: article
            })
    } catch (error) {
        next(error)
    }

}

//更新标签
const updateArticleController = async (req, res, next) => {
    try {
        //获取参数: slug
        const { slug } = req.params
        //更新数据: body
        const data = req.body.article
        //获取文章作者
        let article = await Article.findByPk(slug)
        // console.log(article);
        const authorEmail = article.userEmail
        //获取当前登录用户
        const loginEmail = req.user.email
        //验证:文章真实作者和登录的作者是同一个人
        //修改人的权限通过:文章作者email =登录用户email
        if (authorEmail !== loginEmail) {
            throw new HttpException('403', "只有作者账号才能有修改权限", 'Only the author account can be modified')
        }

        //文章修改
        //获取更新字段
        //更新操作
        const title = data.title
        // console.log(title);
        const description = data.description
        const body = data.body
        // const tags =data.tags['html']
        const updateArticle = await article.update({ title, description, body })
        // console.log(updateArticle);
        //更新后的数据处理: handleArticle
        article = await Article.findByPk(slug, { include: Tag })
        let author = await User.findByPk(loginEmail)
        //响应数据
        article = handleArticle(article, author)

        return res.status(200)
            .json({
                status: 1,
                message: "更新标签成功",
                data: article
            })
    } catch (error) {
        next(error)
    }
}
//删除标签
const deleteArticleController = async (req, res, next) => {
    try {
        //获取参数: slug
        const { slug } = req.params
        //获取文章作者
        let article = await Article.findByPk(slug)
        if (!article) {
            throw HttpException("403", "文章不存在", "article is not finded")
        }
        const authorEmail = article.userEmail
        //获取当前登录用户
        const loginEmail = req.user.email
        //验证:文章真实作者和登录的作者是同一个人
        //修改人的权限通过:文章作者email =登录用户email
        if (authorEmail !== loginEmail) {
            throw new HttpException('403', "只有作者账号才能有修改权限", 'Only the author account can be modified')
        }
        //删除文章
        // let deleteResult=await Article.destroy({where:{slug:slug}})
        let deleteResult = await article.destroy()
        // console.log(deleteResult)
        return res.status(200)
            .json({
                status: 1,
                message: "OK",
                data: article
            })
    } catch (error) {
        next(error)
    }
}
//获取单个文章
const getArticleController = async (req, res, next) => {
    try {
        const { slug } = req.params
        console.log(slug);
        //标签获取 & 作者信息
        let article = await Article.findByPk(slug, { include: Tag })
        let author = await article.getUser()
        // console.log(author);
        // console.log(article.__proto__);  //的方法getUser
        //标签获取 直接{inclide:Tag}  关联查询
        //作者信息 ：一种 查看自己文章：一种查看别人文章
        // console.log(author);

        //喜欢信息
        //喜欢数量
        const { favoriteCount, favorited } = await getFavorite(article, req.user)
        // console.log(favoriteCount, favorited);
        article = await handleArticle(article, author, favoriteCount, favorited)
        return res.status(200)
            .json({
                status: 1,
                message: "获取作者信息成功",
                data: article
            })
    } catch (error) {
        next(error)
    }
}
//获取多个文章:关注作者的文章
const getFollowArticleController = async (req, res, next) => {
    try {
        //获取粉丝email = 就是登录用户
        const fansEmail = req.user.email
        //获取登录用户的关注的作者:followers  中间表
        const query = `SELECT userEmail FROM followers WHERE followerEmail="${fansEmail}"`
        const followAuthors = await sequelize.query(query)
        // console.log(followAuthors[0]);
        //没有关注的作者=>文章就是空数组[]
        if (followAuthors[0].length == 0) {
            return res.status(200)
                .json({
                    status: 1,
                    message: "获取多个文章成功123",
                    data: []// 客户端不显示文章列表 会显示提示
                })
        }
        //有关注的作者=>获取所有作者email [emial1, email...]
        let followAuthorEmails = []
        for (const item of followAuthors[0]) {
            followAuthorEmails.push(item.userEmail)
        }

        //获取每一个作者的所有文章(注意: 每一篇文章都要有标签和作者信息) 
        let { count, rows } = await Article.findAndCountAll({
            distinct: true,//去重
            where: {
                userEmail: followAuthorEmails//可以直接等于一个数组
            },
            include: [Tag, User]
        })
        // console.log("123",rows);
        let articles = []
        for (const t of rows) {
            const { favoriteCount, favorited } = await getFavorite(t, req.user)
            let handleArticle = handleArticle2(t, favoriteCount, favorited)
            articles.push(handleArticle)
        }
        // console.log(articles);
        //处理每个一作者的每一个篇文章都要处理:标签和作者信息
        return res.status(200)
            .json({
                status: 1,
                message: "获取多个文章成功",
                data: {articles,count}
            })

    } catch (error) {
        next(error)
    }
}

//获取文章列表：全局文章 条件查询 author / tag / limit：限制 / offset:偏移量
//场景: 1)获取作者自己的文章2)获取作者喜欢的文章3)获取标签过滤的文章
const getArticlesController = async (req, res, next) => {
    try {
        const email = req.user ? req.user.email : null
        //获取 author / tag / limit /offset < =req.query

        const { favorite, author, tag, limit = 10, offset = 0 } = req.query

        let result;

        if (tag && !author && !favorite) {  // 过滤标签
            result = await Article.findAndCountAll({
                distinct: true,
                include: [
                    { model: Tag, attributes: ['name'], where: { name: tag } },
                    { model: User, attributes: ['email', 'username', 'bio', 'avatar'] }
                ],
                limit: parseInt(limit),
                offset: parseInt(offset)
            })//批量查询
        }

        if (!tag && author && !favorite) {  //获取作者自己文章
            result = await Article.findAndCountAll({
                distinct: true,
                include: [
                    { model: Tag, attributes: ['name'] },
                    { model: User, attributes: ['email', 'username', 'bio', 'avatar'], where: { username: author } }
                ],
                limit: parseInt(limit),
                offset: parseInt(offset)
            })//批量查询
        }

        if (tag && author && !favorite) {  //作者&标签
            result = await Article.findAndCountAll({
                distinct: true,
                include: [
                    { model: Tag, attributes: ['name'] },
                    { model: User, attributes: ['email', 'username', 'bio', 'avatar'] }
                ],
                limit: parseInt(limit),
                offset: parseInt(offset)
            })//批量查询
        }
        //favorite作者  favorite标记代表查询 作者喜欢的文章
        if (favorite && !tag && !author) {//获取作者喜欢的文章
            const authorName = favorite
            const author = await User.findOne({
                where: { username: authorName }
            })

            const authorEmail = author.email
            const queryStying = `SELECT articleSlug from favorites WHERE userEmail = "${authorEmail}"`
            const queryResult = await sequelize.query(queryStying)

            // const result = queryResult[0]
            console.log(queryResult);
            if (queryResult[0].length === 0) {
                return res.status(200)
                    .json({
                        status: 1,
                        message: '没有喜欢的文章',
                        data: []
                    })
            }
            let articleSlugs = []
            for (const item of queryResult[0]) {
                articleSlugs.push(item.articleSlug)
            }
            result = await Article.findAndCountAll({
                distinct: true,
                where: {
                    slug: articleSlugs
                },
                include: [Tag, User]
            })
            console.log('backend-article',result);


        }

        if (!tag && !author && !favorite) { //全局查询
            result = await Article.findAndCountAll({
                distinct: true,
                include: [
                    { model: Tag, attributes: ['name'] },
                    { model: User, attributes: ['email', 'username', 'bio', 'avatar'] }
                ],
                limit: parseInt(limit),
                offset: parseInt(offset)
            })//批量查询
        }
        const { count, rows } = result
        let articles = []
        for (const t of rows) {
            const { favoriteCount, favorited } = await getFavorite(t, req.user)
            let handleArticle = handleArticle2(t, favoriteCount, favorited)
            articles.push(handleArticle)
        }
        return res.status(200)
            .json({
                status: 1,
                message: "获取文章列表成功",
                data: { articles, count }
            })
    } catch (error) {
        next(error)
    }
}
module.exports = {
    createArticleController,
    updateArticleController,
    deleteArticleController,
    getArticleController,
    getFollowArticleController,
    getArticlesController
}